/*
Brick And Blast, a crossplatform breakout game.
 Copyright (C) 2008-2010 Julien CLEMENT (andematunum@gmail.com)
 
 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

#ifndef _Level_h_
#define _Level_h_

#include "SDL_video.h"
#include "GameObject.h"
#include "BnbException.h"
#include "Collision.h"
//#include "LevelIO.h"
#include <list>
#include <set>
#include <iostream>
using namespace std;


/**
* file   Level.h
* date   Mar 22 déc 2009 19:14:01 CET
* brief  Main class for any bnb level.
*/

class Ball;
class Bat;
class Bumper;
class Edge;

#define BAT_MAX_CHUNKS  (7)

class Level {
public:
  /** Loads a level in memory given a filename. */
  Level (const char* file);
  ~Level ();
  /** Initialize various things. */
  void init ();
  /** Called once for all the levels to
    * load all the static resources.
    */
  static void load_resources() throw(BnbException);
  /** Called once for all the levels to
    * free all the static resources.
    */
  static void free_resources();
  /** Get the ball texture */
  static SDL_TextureID get_ball () {
    return tball_;
  }
  /** Get the bumper texture */
  static SDL_TextureID get_bumper () {
    return tbumper_;
  }
  /** Get the bat texture (left border) */
  static SDL_TextureID get_bat_left () {
    return tbat_left_;
  }
  /** Get the bat texture (right border) */
  static SDL_TextureID get_bat_right () {
    return tbat_right_;
  }
  /** Get the bat texture (chunk)  */
  static SDL_TextureID get_bat_chunk () {
    return tbat_chunk_;
  }
  /** Test only: get board texture */
  static SDL_TextureID get_board () {
    return tboard_;
  }
  /** Get the edge texture */
  static SDL_TextureID get_edge () {
    return tedge_;
  }
  /** Called by the specifid create_* methods. */
  void create_object (GameObject* obj) {
    objs_.push_back(obj);
    grid_.add_object(obj);
  }
  /** Create a new ball and add it to the list of balls.
    * \param x  x position of the ball, -1 to choose randomly
    * \param y  y position of the ball, -1 to choose randomly
    * \param angle angle of the ball, 10. to choose randomly
    * \param velocity velocity of the ball, -1 to choose randomly in [1.0,5.0]
    * \return The newly created ball
    */
  Ball* create_ball (SDL_Point& xy, double angle = M_PI, double velocity = 1.);
  /** Create a bat (unique). It is automatically x-centered on the screen.
    * \param nchunks Number of chunks between the bat borders (min:1 max:5)
    */
  Bat* create_bat (int nchunks);
  /** Create a new bumper. */
  Bumper* create_bumper (SDL_Point& xy);
  /** Create the edges.
    * \param size Size of each edge lanes.
    */
  void create_edges (int size);
  /** Called by the specific destroy_* methods. */
  void destroy_object (GameObject* obj) {
    grid_.remove_object(obj);
    objs_.remove(obj);
  }
  /** Destroy a ball. */
  void destroy_ball (Ball* ball);
  /** Destroy the bat. */
  void destroy_bat (Bat* bat);
  /** Destroy a bumper */
  void destroy_bumper (Bumper* bumper);
  /** Destroy the edges */
  void destroy_edges ();
  /** Run the event loop. */
  void run ();
  /** Update all the objects. */
  void update_all ();
  /** Update the balls. */
  void update_balls ();
  /** Update the bat. */
  void update_bat ();
  /** Update the bumpers */
  void update_bumpers ();
  /** Update the edges */
  void update_edges ();
  /** Handle the collisions between an object and its neighbors.
    * Build new CollisionInfo objects if necessary.
    *
    * \sa Collider
    * \sa CollisionInfo
    */
  void detect_neighborhood_collisions (GameObject& obj, set<GameObject*>& neighborhood);
  /** Handle all the collisions which occured. */
  void handle_collisions ();

  /** Load a surface from a file. */
  static void load_surface(SDL_Surface*& surf, const char* file)
                                            throw(BnbException);
  /** Load a texture from a file.
      \sa loadSurface */
  static void load_texture(SDL_TextureID& texid, const char* file)
                                            throw(BnbException);
  /** Load a level from an ascii file.*/
  void load_from_file (const char* file) throw(BnbException);

private:
  /** static resources never change during
    * the execution of a level, or between
    * a level and the other. Other resources
    * are transient.
    */
  static SDL_TextureID  tboard_;
  static SDL_TextureID  tedge_;
  static SDL_TextureID  tbumper_;
  static SDL_TextureID  tball_;
 /* static SDL_Surface* sbat_;*/
  static SDL_TextureID  tbat_left_;
  static SDL_TextureID  tbat_right_;
  static SDL_TextureID  tbat_chunk_;
  static SDL_Surface* sbricks_;
  static SDL_Surface* soptsel_;
  /** List of all the objects */
  list<GameObject*> objs_;
  /** List of balls */
  list<Ball*> balls_;
  /** List of bumpers */
  list<Bumper*> bumpers_;
  /** Bat */
  Bat* bat_;
  /** List of edges */
  list<Edge*> edges_;
  /** Set of collisions */
  set<Collision*,Collision> collisions_;
  /** Grid */
  ObjectGrid grid_;

  /** $$ TMP: need a more complete mouse state object */
  int mouse_x_;
};

#endif

